from exceptions import LiquidMissingTagHandlerError
from utils import Registry, unpack_block, camel2snake


class TagManager:
    __registry__ = Registry(custom_error=LiquidMissingTagHandlerError)

    @classmethod
    def _get_tag_term(cls, child):
        """
        查找名字的优先级
        name属性 -> 类名除去Tag前缀
        """

        def _get_tag_term_from_clsname():
            import sys

            if sys.version_info.minor >= 9:
                return child.__name__.removeprefix("Tag")
            else:
                return child.__name__[len("Tag"):]

        return getattr(cls, "name", camel2snake(_get_tag_term_from_clsname()))

    def __init_subclass__(cls, **init_params):
        """
        直接将子类注册到父类下，
        这样可以避免使用register等装饰器去实现
        """

        # NOTE: 标签名，将被使用在parse过程中
        # NOTE: 使用这个名字作为词法树中的节点名,并且用于匹配。
        tag_term = TagManager._get_tag_term(cls)

        # NOTE: 支持别名
        alias_names = init_params.get("alias", [])
        if isinstance(alias_names, str):
            alias_names = [alias_names]

        TagManager.__registry__.add_handler_cls(tag_term, alias_names, cls)

        return cls

    @classmethod
    def get_tag(cls, term_or_alias):
        return getattr(cls.__registry__, term_or_alias)

    @classmethod
    def handle(cls, tag_block, context: dict = None, transformer=None):
        tag_name, block = unpack_block(tag_block)
        handler = cls.get_tag(tag_name)
        return handler.render(block, context, transformer)
